/*
PearReview - The peer review assistant.
Copyright (C) 2009  Dimitrij Pankratz, Anton Musichin
http://www.pearreview.com, info@pearreview.com

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/

package com.pearreview.application;

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Image;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.reflect.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

import javax.swing.*;
import javax.swing.event.ChangeListener;

import com.pearreview.ui.PearPanel;
import com.pearreview.ui.PearToolBar;
import com.pearreview.ui.ToolBarButtonUI;
import com.pearreview.util.DoubleClickMouseAdapter;
import com.pearreview.moderatorplugin.ModeratorPlugin;
import com.pearreview.reviewerplugin.ReviewerPlugin;
import com.pearreview.scribeplugin.ScribePlugin;

public class PearReview extends PearReviewFrame {
	
	private static final long serialVersionUID = -7660681714409378125L;
	
	public static final Version VERSION = new Version(0, 9, 0, 0);
	
	public static final String TITLE = "PearReview";
	
	private static final Locale[] SUPPORTED_LOCALES = {
			new Locale("de", Locale.getDefault().getCountry()), 
			new Locale("en", Locale.getDefault().getCountry()), 
			new Locale("ru", Locale.getDefault().getCountry())};
	
	private static final File WORKSPACE = 
			new File("workspace/");
	private static final File AUTO_SAVE_FILE = 
			new File(WORKSPACE, "session" + PRSFilter.EXTENSION);
	private static final File PREFERENCES_FILE = 
			new File(WORKSPACE, "preferences" + PRPFilter.EXTENSION);
	private static final File FILE_HISTORY_FILE = 
			new File(WORKSPACE, "history" + PRHFilter.EXTENSION);
	
	/**
	 * Plugin information list.
	 * Plugin information list should be initialized at start only.
	 */
	private PluginInformation[] availablePlugins;
	
	/**
	 * MenuItems event listener
	 */
	private Action exitAction;
	private Action fullScreenAction; 
	private Action propertiesAction;
	private Action helpAction;
	private Action newTabAction;
	private Action closeTabAction;
	private Action aboutAction;
	private Action licenseAction;
	private Action exportAction;
	private Action importAction;
	private UpdateAction updateAction;
	
	private VersionChecker versionChecker;
	
	private SaveTimer saveTimer;
	private Preferences preferences;
	
	private SpringGlassPane glassPane;
	private FileHistory fileHistory;
	
	//private java.awt.PopupMenu dockMenu;
	
	/**
	 * View tab close button listener
	 */
	private ViewCloseListener viewCloseListener = 
			new ViewCloseButtonListener();
	
	public static void main(String[] args) {
		
		SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				installLAF();
				
				JFrame frame = new PearReview();
				frame.pack();
				
				/* set frame size */
				Dimension frameSize = new Dimension(1000, 700);
				Dimension minFrameSize = new Dimension(600, 400);
				frame.setSize(frameSize);
				frame.setPreferredSize(frameSize);
				frame.setMinimumSize(minFrameSize);

				/* show frame centered */
				Dimension screenSize = 
						Toolkit.getDefaultToolkit().getScreenSize();
				int top = (screenSize.height - frameSize.height) / 2;
				int left = (screenSize.width - frameSize.width) / 2;
				frame.setLocation(left, top);
				
				frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
				frame.setVisible(true);
			}
		});
	}
	
	private static void installLAF() {
		if(isMacOSX()) {
			
			/* this property will have no effect. the correct property has
			 * to be passed to JVM with -Xdock:name=PearReview
			 */
			System.setProperty(
					"com.apple.mrj.application.apple.menu.about.name", TITLE);
		}
		try {
			UIManager.setLookAndFeel(
					UIManager.getSystemLookAndFeelClassName());
		} catch (Exception exc) {
			// Do nothing...
		}
	}
	
	private PearReview() {
		super(TITLE);
		
		/* set application icon */
		ImageIcon image = getResourceIcon("osx_dock_icon.png");
		setIconImage(image.getImage());
		
		/* add view close listener */
		addViewCloseListener(viewCloseListener);
		
		/* add window listener */
		addWindowListener(new WindowListener() {
			@Override
			public void windowOpened(WindowEvent e){
				opened();
			}
			@Override
			public void windowClosing(WindowEvent e){
				quit();
			}
			@Override
			public void windowClosed(WindowEvent e){}
			@Override
			public void windowIconified(WindowEvent e){}
			@Override
			public void windowDeiconified(WindowEvent e){}
			@Override
			public void windowActivated(WindowEvent e){}
			@Override
			public void windowDeactivated(WindowEvent e){}
		});
		
		/* add application listener for mac os x */
		if(isMacOSX()) {
			
			/* add application listener */
			try {
				Class<?> applicationClass = 
						Class.forName("com.apple.eawt.Application");
				Object macOSXApplication = applicationClass.newInstance();
				Class<?> applicationListenerClass = 
						Class.forName("com.apple.eawt.ApplicationListener");
				Method addListenerMethod = applicationClass.getDeclaredMethod(
						"addApplicationListener", applicationListenerClass);
				
				InvocationHandler handler = new InvocationHandler() {
					@Override
					public Object invoke(Object proxy, Method method, 
							Object[] args) throws Throwable {
						Object event = args[0];
						if(method.getName().equals("handleQuit")) {
							invokeMethod("quit");
							setHandled(event, false);
						} else if(method.getName().equals("handleAbout")) {
							invokeMethod("about");
							setHandled(event, true);
						} else if(method.getName().equals("handlePreferences")){
							invokeMethod("preferences");
							setHandled(event, true);
						}
						return null;
					}
					
					public void invokeMethod(String m) throws Throwable {
						PearReview.this.getClass().getDeclaredMethod(m)
								.invoke(PearReview.this);
					}
					
					public void setHandled(Object event, boolean handled) 
							throws Throwable {
						Method setHandledMethod = event.getClass()
								.getDeclaredMethod("setHandled", boolean.class);
						setHandledMethod.invoke(event, handled);
					}
				};
				
				Object osxAdapterProxy = Proxy.newProxyInstance(
						getClass().getClassLoader(), 
						new Class[]{applicationListenerClass}, 
						handler);
				
				/* add listener */
				addListenerMethod.invoke(macOSXApplication, osxAdapterProxy);
				
				/* enable about menu */
				Method enableAboutMethod = applicationClass.getDeclaredMethod(
						"setEnabledAboutMenu", boolean.class);
				enableAboutMethod.invoke(macOSXApplication, true);
				
				/* enable preferences menu */
				Method enablePrefsMethod = applicationClass.getDeclaredMethod(
						"setEnabledPreferencesMenu", boolean.class);
				enablePrefsMethod.invoke(macOSXApplication, true);
				
				/* set dock icon image */
				Method setDockIconMethod = applicationClass.getDeclaredMethod(
						"setDockIconImage", Image.class);
				setDockIconMethod.invoke(macOSXApplication, image.getImage());
				
				/* set dock icon badge */
				/* the dock icon badge is a small notifying feature, 
				 * but only good for displaying very short words or numbers */
				/*
				Method setDockIconBadgeMethod = applicationClass
						.getDeclaredMethod("setDockIconBadge", String.class);
				setDockIconBadgeMethod.invoke(macOSXApplication, "Update");
				*/
				
				/*
				PopupMenu dockMenu = new PopupMenu("Hello");
				dockMenu.add("Ciao");
				add(dockMenu);
				
				Method setDockMenuMethod = applicationClass.getDeclaredMethod(
						"setDockMenu", java.awt.PopupMenu.class);
				setDockMenuMethod.invoke(macOSXApplication, dockMenu);
				*/
				
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		
		/* initialize glasspane */
		glassPane = new SpringGlassPane();
		setGlassPane(glassPane);
		glassPane.setVisible(true);
		
		/* initialize plugins */
		initializeAvailablePlugins();
		
		/* initialize saver timer */
		saveTimer = new SaveTimer();
		
		/* initialize/set/apply preferences */
		Preferences preferences = readPreferences();
		if(preferences == null) {
			preferences = getDefaultPreferences();
		}
		setPreferences(preferences, true);
		
		/* initialize menu actions */
		exitAction = new ExitAction(); 
		fullScreenAction = new FullScreenAction(); 
		propertiesAction = new PropertyAction();
		helpAction = new ShowHelpAction();
		newTabAction = new NewTabAction();
		closeTabAction = new CloseTabAction();
		aboutAction = new AboutAction();
		licenseAction = new LicenseAction();
		exportAction = new ExportAction();
		importAction = new ImportAction();
		updateAction = new UpdateAction();
		
		/* initialize updater */
		versionChecker = new VersionChecker();
		versionChecker.addActionListener(updateAction);
		
		/* initialize file history */
		fileHistory = readFileHistory();
		if(fileHistory == null) {
			fileHistory = new FileHistory();
		}
		
		/* restore save data if available */
		if(AUTO_SAVE_FILE.exists()) {
			readPluginSaveData();
		} else {
			addView(createStartView());
		}
	}
	
	private Preferences getPreferences() {
		Preferences prefs = preferences;
		if(prefs == null) {
			prefs = getDefaultPreferences();
		}
		
		return prefs;
	}
	
	private void setPreferences(Preferences prefs, boolean start) {
		preferences = prefs;
		Object interval = prefs.getValue(Preferences.SAVE_INTERVAL_KEY);
		Object locale = prefs.getValue(Preferences.LOCALE_KEY);
		Object fullScreen = prefs.getValue(Preferences.FULL_SCREEN_OPTION_KEY);
		
		if(interval instanceof Long) {
			saveTimer.setInterval((Long) interval);
		}
		if(start && locale instanceof Locale) {
			Locale.setDefault((Locale) locale);
		}
		if(fullScreen instanceof Boolean) {
			setFullScreenExclusiveModeEnabled((Boolean) fullScreen);
		}
		
		if(!start) {
			writePreferences(preferences);
		}
	}
	
	private void setPreferences(Preferences prefs) {
		setPreferences(prefs, false);
	}
	
	/**
	 * Returns the default preferences of the program.
	 * @return default preferences
	 */
	public static Preferences getDefaultPreferences() {
		Preferences prefs = new Preferences();
		
		prefs.putValue(Preferences.LOCALE_KEY, 
				getDefaultLocale());
		prefs.putValue(Preferences.SAVE_INTERVAL_KEY, 
				getDefaultSaveInterval());
		prefs.putValue(Preferences.SESSION_OPTION_KEY, 
				getDefaultSessionOption());
		prefs.putValue(Preferences.UPDATE_OPTION_KEY,
				getDefaultUpdateOption());
		prefs.putValue(Preferences.FULL_SCREEN_OPTION_KEY, 
				getDefaultFullScreenOption());
		
		return prefs;
	}
	
	/**
	 * Returns the default save interval of the program.
	 * @return default save interval
	 */
	public static long getDefaultSaveInterval() {
		return 3L * 60L * 1000L;
	}
	
	/**
	 * Returns the default update option of the program.
	 * @return default update option
	 */
	public static Boolean getDefaultUpdateOption() {
		return true;
	}
	
	/**
	 * Returns the default session option of the program.
	 * @return default session option
	 */
	public static Boolean getDefaultSessionOption() {
		return true;
	}
	
	/**
	 * Returns the default locale of the program.
	 * @return default locale
	 */
	public static Locale getDefaultLocale() {
		String lang = Locale.getDefault().getLanguage();
		for(Locale l: SUPPORTED_LOCALES) {
			if(lang.equals(l.getLanguage())) {
				return l;
			}
		}
		return new Locale("en");
	}
	
	/**
	 * Returns the default full screen exclusive mode option of the program.
	 * @return default exclusive mode option
	 */
	public static boolean getDefaultFullScreenOption() {
		return true;
	}
	
	/**
	 * Quits the application
	 * Every plugin in View will be checked by 
	 * <code>close</code> method if it can be closed.
	 * If one of active plugins returns <code>false</code> the 
	 * application don not close.
	 */
	public void quit() {
		Object sessionOption = getPreferences().getValue(
				Preferences.SESSION_OPTION_KEY);
		boolean save = Boolean.TRUE.equals(sessionOption);
		boolean saveTimerEnabled = saveTimer.isEnabled();
		saveTimer.setEnabled(false);
		
		/* close tabs, if session could not be written */
		if(!save || !writePluginSaveData()) {
			View views[] = getViews();
			for(int i = views.length - 1 ; i >= 0; i-- ) {
				if(!closeView(views[i])) {
					saveTimer.setEnabled(saveTimerEnabled);
					return;
				}
			}
		}
		
		/* execute at last */
		if(!save) {
			AUTO_SAVE_FILE.delete();
		}
		
		/* file history */
		writeFileHistory(fileHistory);
		
		System.exit(0);
	}
	
	/**
	 * Shows about dialog
	 */
	public void about() {
		AboutBox about = new AboutBox(this);
		
		glassPane.setFaded(true);
		about.setVisible(true);
		glassPane.setFaded(false);
	}
	
	/**
	 * Shows preferences dialog
	 */
	public void preferences() {
		PreferencesBox pref = new PreferencesBox(this, SUPPORTED_LOCALES);
		
		pref.setDefaultPreferences(getDefaultPreferences());
		pref.setPreferences(getPreferences());
		pref.setWorkspace(WORKSPACE);
		
		glassPane.setFaded(true);
		pref.setVisible(true);
		glassPane.setFaded(false);
		
		// apply new preferences
		Preferences newPreferences = pref.getPreferences();
		if(newPreferences != null) {
			setPreferences(newPreferences);
		}
	}
	
	/**
	 * Closes the View <code>v</code>.
	 * If view contains a plugin this will be checked by 
	 * <code>close</code> method if it can be closed.
	 * @param v view to close
	 * @return if view's <code>source</code> is not a plugin returns true,
	 * otherwise the return value of method <code>close</code> of plugin.
	 */
	private boolean closeView(View v) {
		Object viewSource = v.getSource();
		if(viewSource != null && viewSource instanceof Plugin) {
			Plugin plugin = (Plugin)viewSource;
			if(plugin.close()) {
				removeView(v);
				return true;
			} else {
				return false;
			}
		} else {
			removeView(v);
			return true;
		}		
	}
	
	/**
	 * Gets called if frame is shown.
	 */
	private void opened() {
		validateView(getSelectedViewIndex());
		getContentPane().requestFocusInWindow();
		
		/* check for update */
		Object updateOption = getPreferences().getValue(
				Preferences.UPDATE_OPTION_KEY);
		if(Boolean.TRUE.equals(updateOption)) {
			updateAction.setBusy(true);
			versionChecker.check();
		}
	}
	
	/**
	 * Saves the current session
	 */
	private boolean writePluginSaveData(File file) {
		try {
			if(!file.exists() && sizeView() == 1 && 
					!(getView(0).getSource() instanceof Plugin)) {
				return true;
			}
		} catch(Throwable e) {
			// ignore
		}
		List<Object> lst = new ArrayList<Object>();
		View views[] = getViews();
		for(int i = 0 ; i < views.length ; i++ ) {
			if(views[i].getSource() instanceof Plugin) {
				Plugin plug = (Plugin)views[i].getSource();
				lst.add(plug.getClass().toString());
				lst.add(plug.getSaveData());
			} else {
				lst.add(null);
				lst.add(null);
			}
		}
		
		// set at last position selected tab
		lst.add(getSelectedViewIndex());
		Object[] saveData = new Object[lst.size()];
		lst.toArray(saveData);
		
		FileOutputStream fos = null;
		ObjectOutputStream oos = null;
		BufferedOutputStream bos = null;
		
		try {
			file.getParentFile().mkdirs();
		} catch(Throwable th) {
			// ignore
		}
		
		try {
			fos = new FileOutputStream(file);
			bos = new BufferedOutputStream(fos);
			oos = new ObjectOutputStream(bos);
			
			oos.writeObject(saveData);
			
			oos.close();
			
			return true;
			
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO error message?!
			e.printStackTrace();
			
			if(oos != null) {
				try {
					oos.close();
				} catch (IOException e1) {
					// do nothing
				}
			} else if(bos != null) {
				try {
					bos.close();
				} catch (IOException e1) {
					// do nothing
				}
			}
			try {
				file.delete();
			} catch(Throwable e1) {
				// do nothing
			}
		}
		
		return false;
	}
	
	/**
	 * Saves the current session
	 */
	private boolean writePluginSaveData() {
		return writePluginSaveData(AUTO_SAVE_FILE);
	}
	
	/**
	 * Reads plugin save data
	 */
	private void readPluginSaveData(File file) {
		FileInputStream fis = null;
		BufferedInputStream bis = null;
		ObjectInputStream ois = null;
		
		try {
			fis = new FileInputStream(file);
			bis = new BufferedInputStream(fis);
			ois = new ObjectInputStream(bis);
			
			Object obj = ois.readObject();
			
			ois.close();
			
			clearViews();
			
			Object[] saveData = (Object[]) obj;
			for(int i = 0 ; i < saveData.length - 1 ; i += 2) {
				try {
					String clazz = (String)saveData[i];
					SaveData asd = (SaveData)saveData[i+1];
					
					if(clazz == null) {
						addView(createStartView());
						continue;
					}
					
					Plugin plugin = getPlugin(clazz);
					
					plugin.loadSaveDataOnRun(asd);
					
					final View view = new View();
					final MenuBarAdapter menuBarAdapter = 
							createMenuBarAdapter();
					
					setPluginView(view, plugin, menuBarAdapter);
					addView(view);
					
				} catch(Exception e) {
					// TODO error message?!
					e.printStackTrace();
					// nothing to do
				}
			}
			try {
				int select = (Integer)saveData[saveData.length - 1];
				setSelectedView(select);
			} catch(IndexOutOfBoundsException e) {
				// do nothing
			}
			
		} catch (FileNotFoundException e) {
			// do nothing
		} catch(IOException e) {
			// TODO error message?!
			
			e.printStackTrace();
			if(bis != null) {
				try {
					bis.close();
				} catch(IOException e1) {
					// do nothing
				}
			} else if(ois != null) {
				try {
					ois.close();
				} catch (IOException e1) {
					// do nothing
				}
			}
			
			try {
				file.delete();
			} catch(Throwable e1) {
				// do nothing
			}
		} catch (ClassNotFoundException e) {
			// TODO error message?!
			// should never occurred if file created by writePluginSaveData
			e.printStackTrace();
		}
		
		if(sizeView() <= 0)
			addView(createStartView());
	}
	
	/**
	 * Reads plugin save data
	 */
	private void readPluginSaveData() {
		readPluginSaveData(AUTO_SAVE_FILE);
	}
	
	private boolean writePreferences(Preferences preferences) {
		return writePreferences(preferences, PREFERENCES_FILE);
	}
	
	private boolean writePreferences(Preferences preferences, File file) {
		FileOutputStream fos = null;
		ObjectOutputStream oos = null;
		BufferedOutputStream bos = null;
		
		try {
			file.getParentFile().mkdirs();
		} catch(Throwable th) {
			// ignore
		}
		
		try {
			fos = new FileOutputStream(file);
			bos = new BufferedOutputStream(fos);
			oos = new ObjectOutputStream(bos);
			
			oos.writeObject(preferences);
			
			oos.close();
			
			return true;
			
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO error message?!
			e.printStackTrace();
			
			if(oos != null) {
				try {
					oos.close();
				} catch (IOException e1) {
					// do nothing
				}
			} else if(bos != null) {
				try {
					bos.close();
				} catch (IOException e1) {
					// do nothing
				}
			}
			try {
				file.delete();
			} catch(Throwable e1) {
				// do nothing
			}
		}
		
		return false;
	}
	
	private Preferences readPreferences() {
		return readPreferences(PREFERENCES_FILE);
	}
	
	private Preferences readPreferences(File file) {
		FileInputStream fis = null;
		BufferedInputStream bis = null;
		ObjectInputStream ois = null;
		
		try {
			fis = new FileInputStream(file);
			bis = new BufferedInputStream(fis);
			ois = new ObjectInputStream(bis);
			
			Object obj = ois.readObject();
			
			ois.close();
			
			return (Preferences) obj;
			
		} catch (FileNotFoundException e) {
			// do nothing
		} catch(Throwable e) {
			// TODO error message?!
			
			e.printStackTrace();
			if(bis != null) {
				try {
					bis.close();
				} catch(IOException e1) {
					// do nothing
				}
			} else if(ois != null) {
				try {
					ois.close();
				} catch (IOException e1) {
					// do nothing
				}
			}
			
			try {
				file.delete();
			} catch(Throwable e1) {
				// do nothing
			}
		}
		
		return null;
	}
	
	private boolean writeFileHistory(FileHistory fileHistory) {
		return writeFileHistory(fileHistory, FILE_HISTORY_FILE);
	}
	
	/**
	 * Writes file history to the file
	 * @param fileHistory history to write
	 * @param file to write in this given file
	 * @return <code>true</code> if success otherwise <code>false</code>
	 */
	private boolean writeFileHistory(FileHistory fileHistory, File file) {
		try {
			if(!file.exists() && fileHistory.isEmpty()) {
				return true;
			}
		} catch(Throwable e) {
			// ignore
		}
		
		FileOutputStream fos = null;
		ObjectOutputStream oos = null;
		BufferedOutputStream bos = null;
		
		try {
			file.getParentFile().mkdirs();
		} catch(Throwable th) {
			// ignore
		}
		
		try {
			fos = new FileOutputStream(file);
			bos = new BufferedOutputStream(fos);
			oos = new ObjectOutputStream(bos);
			
			oos.writeObject(fileHistory);
			
			oos.close();
			
			return true;
			
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO error message?!
			e.printStackTrace();
			
			if(oos != null) {
				try {
					oos.close();
				} catch (IOException e1) {
					// do nothing
				}
			} else if(bos != null) {
				try {
					bos.close();
				} catch (IOException e1) {
					// do nothing
				}
			}
			try {
				file.delete();
			} catch(Throwable e1) {
				// do nothing
			}
		}
		
		return false;
	}
	
	private FileHistory readFileHistory() {
		return readFileHistory(FILE_HISTORY_FILE);
	}
	
	private FileHistory readFileHistory(File file) {
		FileInputStream fis = null;
		BufferedInputStream bis = null;
		ObjectInputStream ois = null;
		
		try {
			fis = new FileInputStream(file);
			bis = new BufferedInputStream(fis);
			ois = new ObjectInputStream(bis);
			
			Object obj = ois.readObject();
			
			ois.close();
			
			return (FileHistory) obj;
			
		} catch (FileNotFoundException e) {
			// do nothing
		} catch(Throwable e) {
			// TODO error message?!
			
			e.printStackTrace();
			if(bis != null) {
				try {
					bis.close();
				} catch(IOException e1) {
					// do nothing
				}
			} else if(ois != null) {
				try {
					ois.close();
				} catch (IOException e1) {
					// do nothing
				}
			}
			
			try {
				file.delete();
			} catch(Throwable e1) {
				// do nothing
			}
		}
		
		return null;
	}
	
	/**
	 * Returns a new plugin instance if plugin name. 
	 * @param name plugin name to instantiate
	 * @return plugin instance
	 */
	private Plugin getPlugin(String name) {
		for(int i = 0 ; i < availablePlugins.length ; i++) {
			if(availablePlugins[i].getPluginClass().toString().equals(name)) {
				return availablePlugins[i].newPluginInstance();
			}
		}
		return null;
	}
	
	/**
	 * Initializes the available plugins.
	 * All available plugins will be stored to <code>availablePlugins</code>.
	 */
	private void initializeAvailablePlugins() {
		availablePlugins = new PluginInformation[3];
		
		/* reviewer plugin */
		availablePlugins[2] = new PluginInformation() {
			private final ImageIcon icon = new ImageIcon(
					getClass().getResource("images/plugins/reviewer.png"));
			@Override
			public Plugin newPluginInstance() {		
				return new ReviewerPlugin();
			}
			@Override
			public ImageIcon getPluginIcon() {
				return icon;
			}
			@Override
			public Class<? extends Plugin> getPluginClass() {
				return ReviewerPlugin.class;
			}
			@Override
			public String getPluginTitle() {
				return Messages.getString("PearReview.Reviewer.title");
			}
		};
		
		/* scribe plugin */
		availablePlugins[1] = new PluginInformation() {
			private final ImageIcon icon = new ImageIcon(
					getClass().getResource("images/plugins/scribe.png"));
			@Override
			public Plugin newPluginInstance() {		
				return new ScribePlugin();
			}
			@Override
			public ImageIcon getPluginIcon() {
				return icon;
			}
			@Override
			public Class<? extends Plugin> getPluginClass() {
				return ScribePlugin.class;
			}
			@Override
			public String getPluginTitle() {
				return Messages.getString("PearReview.Scribe.title");
			}
		};
		
		/* moderator plugin */
		availablePlugins[0] = new PluginInformation() {
			private final ImageIcon icon = new ImageIcon(
					getClass().getResource("images/plugins/moderator.png"));
			@Override
			public Plugin newPluginInstance() {		
				return new ModeratorPlugin();
			}
			@Override
			public ImageIcon getPluginIcon() {
				return icon;
			}
			@Override
			public Class<? extends Plugin> getPluginClass() {
				return ModeratorPlugin.class;
			}
			@Override
			public String getPluginTitle() {
				return Messages.getString("PearReview.Moderator.title");
			}
		};
	}
	
	/**
	 * Creates start view. This is a default view, 
	 * where the user can see and select available plugins.
	 * <code>availablePlugins</code> must be initialized.
	 * @return view
	 */
	private View createStartView() {
		final View view = new View();
		final MenuBarAdapter menuBarAdapter = createMenuBarAdapter();
		
		/* view title */
		view.setTabTitle(Messages.getString("PearReview.container.title"));
		view.setFrameTitle(Messages.getString("PearReview.container.title"));
		
		/* view menu bar */		
		JMenuBar menuBar = menuBarAdapter.getMenuBar();
		view.setMenuBar(menuBar);
		
		/* view component */
		final JList list = new JList(availablePlugins);
		
		list.setCellRenderer(new DefaultListCellRenderer() {
			private static final long serialVersionUID = 7756981693968735666L;
			
			@Override
			public Component getListCellRendererComponent(JList list, 
					Object value, int index, boolean isSelected, 
					boolean cellHasFocus) {
				super.getListCellRendererComponent(list, value,
							index, isSelected, cellHasFocus);
				
				PluginInformation element = (PluginInformation) value;
				setBorder(BorderFactory.createEmptyBorder(32, 32, 32, 32));
				setFont(getFont().deriveFont(18.0f).deriveFont(Font.BOLD));
				setText(element.getPluginTitle());
				setIcon(element.getPluginIcon());
				setHorizontalTextPosition(JLabel.CENTER);
				setVerticalTextPosition(JLabel.BOTTOM);
				if (isSelected) {
					setBackground(new Color(0xbfd72b));
					setForeground(new Color(0x666666));
				} else {
					setBackground(new Color(0x7f7f7f));
					setForeground(new Color(0xdddddd));
				}
				
				return this;
			}
		});
		
		list.setLayoutOrientation(JList.HORIZONTAL_WRAP);
		list.setVisibleRowCount(1);
		list.setBorder(BorderFactory.createEtchedBorder());
		
		list.addMouseListener(new DoubleClickMouseAdapter() {
			private static final long serialVersionUID = 1533007885809302336L;
			@Override
			public void mouseDoubleClicked(MouseEvent e) {
				SpringGlassPane glassPane = 
						(SpringGlassPane) getGlassPane();
				
				int index = list.getSelectedIndex();
				 
				Rectangle bounds = list.getCellBounds(index, index);
				Point location = new Point(bounds.x, bounds.y);
				location = SwingUtilities
						.convertPoint(list, location, glassPane);
				location.y -= 13;
				bounds.setLocation(location);
				
				PluginInformation plugInf = 
						((PluginInformation)list.getSelectedValue());
				 
				Image image = plugInf.getPluginIcon().getImage();
				
				/* create new plugin view */
				final Plugin plugin = plugInf.newPluginInstance();
				setPluginView(view,
						plugin, 
						menuBarAdapter);
				validateView(view);
				
				/* show animation */
				glassPane.showSpring(bounds, image);
			}
		});

		JPanel panel = new PearPanel();
		panel.setLayout(new GridBagLayout());
		
		JLabel topLabel = 
				new JLabel(Messages.getString("PearReview.container.top"));
		topLabel.setFont(new Font("Tahoma", Font.PLAIN, 12));
		topLabel.setForeground(new Color(0x333333));
		//topLabel.setVerticalAlignment(SwingConstants.BOTTOM);
		
		panel.add(topLabel,
				new GridBagConstraints(0, 0, 1, 1, 1.0, 1.0,
					GridBagConstraints.SOUTH, GridBagConstraints.NONE,
					new Insets(0, 0, 0, 0), 0, 0));
		
		panel.add(list, new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0,
				GridBagConstraints.CENTER, GridBagConstraints.NONE,
				new Insets(0, 0, 0, 0), 0, 0));
		
		JLabel bottomLabel = 
				new JLabel(Messages.getString("PearReview.container.bottom"));
		bottomLabel.setFont(new Font("Tahoma", Font.PLAIN, 12));
		bottomLabel.setForeground(new Color(0x333333));
		
		panel.add(bottomLabel,
				new GridBagConstraints(0, 2, 1, 1, 1.0, 1.0,
					GridBagConstraints.NORTH, GridBagConstraints.NONE,
					new Insets(0, 0, 0, 0), 0, 0));
		
		JScrollPane scrollPane = new JScrollPane(panel);
		scrollPane.setBorder(null);		
		view.setComponent(scrollPane);
		
		/* view tool bar */
		view.setToolBar(createToolBar());
		
		/* source */
		view.setSource(this);

		return view;
	}
	
	/**
	 * Creates new plugin view.
	 * @param title title of plugin view
	 * @param v the view
	 * @param p the plugin
	 * @param mba the menu bar adapter
	 */
	private void setPluginView(final View v, final Plugin p,
			final MenuBarAdapter mba) {
		
		final PluginAdapter pa = new PluginAdapter() {
			private static final long serialVersionUID = -8443317950998329359L;
			@Override
			public void close() {
				removeView(v);
		
				if(sizeView() == 0) {
					addView(createStartView());
				}			
			}
			@Override
			public void setTitle(String tabTitle, String frameTitle) {
				v.setTabTitle(tabTitle);
				v.setFrameTitle(frameTitle);
				validate();
			}
			@Override
			public void setTabIcon(Icon icon) {
				v.setIcon(icon);
				validate();
			}
			@Override
			public void newStartTab(boolean select) {
				View v = createStartView();
				addView(v);
				if(select) {
					setSelectedView(v);
				}
			}
			@Override
			public void navigateToStartTab() {
				// TODO do copy!
				if(PearReview.this.containsView(v)) {
					View startView = createStartView();
					int index = PearReview.this.indexOfView(v);
					PearReview.this.setView(index, startView);
				}
			}
			@Override
			public File getWorkspace() {
				return new File(WORKSPACE, p.getClass().getSimpleName());
			}
			@Override
			public SpringGlassPane getSpringGlassPane() {
				return glassPane;
			}
			@Override
			public void newPluginTab(Plugin plugin, boolean select) {
				final View view = new View();
				final MenuBarAdapter menuBarAdapter = createMenuBarAdapter();
				
				setPluginView(view, plugin, menuBarAdapter);
				addView(view);
				
				if(select) {
					setSelectedView(view);
				}
			}
			@Override
			public boolean isFullScreen() {
				return PearReview.this.isFullScreen();
			}
			@Override
			public void setFullScreen(boolean enabled) {
				PearReview.this.setFullScreen(enabled);
				fullScreenAction.putValue(Action.SELECTED_KEY,  
						isFullScreen());
			}
			@Override
			public void addFullScreenListener(ChangeListener cl) {
				PearReview.this.addFullScreenListener(cl);
			}
			@Override
			public void removeFullScreenListener(ChangeListener cl) {
				PearReview.this.removeFullScreenListener(cl);
			}
			@Override
			public FileHistory getFileHistory() {
				return fileHistory;
			}
			@Override
			public MenuBarAdapter getMenuBarAdapter() {
				return mba;
			}
			@Override
			public void setComponent(Component comp) {
				v.setComponent(comp);
				validate();
			}
			@Override
			public void setToolBar(JToolBar toolBar) {
				v.setToolBar(toolBar);
			}
			@Override
			public void setFile(File f) {
				v.setFile(f);
				validate();
			}
			public void validate() {
				if(containsView(v)) {
					validateView(v);
				}
			}
		};
		
		v.setSource(p);
		
		// set default title before you run plugin!
		v.setTabTitle(p.getTitle());
		v.setViewTitle(p.getTitle());
		v.setFrameTitle(null);
		v.setMenuBar(mba.getMenuBar());
		v.setComponent(null);
		v.setToolBar(null);
		
		p.run(pa);
	}
	
	/**
	 * Returns a resource icon
	 * @param name name of icon
	 * @return
	 */
	private ImageIcon getResourceIcon(String name) {
		return new ImageIcon(PearReview.class.getResource("images/" + name));
	}
	
	private MenuBarAdapter createMenuBarAdapter() {
		return new MenuBarAdapter(
				exitAction, 
				fullScreenAction, 
				propertiesAction, 
				helpAction, 
				newTabAction,
				closeTabAction,
				aboutAction,
				licenseAction,
				updateAction,
				exportAction,
				importAction);
	}
	
	private JToolBar createToolBar() {
		JToolBar toolBar = new PearToolBar();
		toolBar.setOpaque(false);
		
		toolBar.setFloatable(false);
		toolBar.setBackground(new Color(0xd6, 0xd6, 0xd6));
		
		toolBar.setBorder(BorderFactory.createMatteBorder(
				0, 0, 1, 0, new Color(0x828790)));
		
		//---- fullscreenBtn ----
		JButton fullscreenBtn = new JButton();
		fullscreenBtn.setAction(fullScreenAction);
		Icon ico_fullscreenBtn = getResourceIcon("fullscreen_hover.png");
		Icon ico_fullscreenBtn_hover = getResourceIcon("fullscreen.png");
		fullscreenBtn.setIcon(ico_fullscreenBtn);
		fullscreenBtn.setUI(new ToolBarButtonUI(ico_fullscreenBtn_hover));
		fullscreenBtn.setToolTipText(
				Messages.getString("PearReview.menu.view.fullscreen"));
		fullscreenBtn.setBackground(new Color(0xd6d6d6));
		fullscreenBtn.setOpaque(false);
		
		//---- newTabBtn ----
		JButton newTabBtn = new JButton();
		newTabBtn.setAction(newTabAction);
		Icon ico_newTabBtn = getResourceIcon("tab-new_toolbar.png");
		Icon ico_newTabBtn_hover = getResourceIcon("tab-new_hover.png");
		newTabBtn.setIcon(ico_newTabBtn);
		newTabBtn.setUI(new ToolBarButtonUI(ico_newTabBtn_hover));
		newTabBtn.setToolTipText(
				Messages.getString("PearReview.menu.file.new_tab"));
		newTabBtn.setBackground(new Color(0xd6d6d6));
		newTabBtn.setOpaque(false);
		
		toolBar.setPreferredSize(new Dimension(Short.MAX_VALUE, 36));
		
		toolBar.add(newTabBtn);
		toolBar.add(fullscreenBtn);
		
		return toolBar;
	}
	
	private class SaveTimer implements ActionListener, Serializable {
		private static final long serialVersionUID = -3364933876090954261L;
		private long lastSave = System.currentTimeMillis();
		private Timer timer;
		private long saveInterval;
		public SaveTimer() {
			this(-1L);
		}
		public SaveTimer(long interval) {
			timer = new Timer(1000, this);
			setInterval(interval);
		}
		private long getDifference() {
			return System.currentTimeMillis() - lastSave;
		}
		public void save() {
			lastSave = System.currentTimeMillis();
			PearReview.this.writePluginSaveData();
		}
		public boolean isEnabled() {
			return timer.isRunning();
		}
		public void setEnabled(boolean enabled) {
			if((timer.isRunning() && !enabled) || getInterval() < 0) {
				timer.stop();
			} else if(!timer.isRunning() && enabled && getInterval() >= 0) {
				timer.start();
			}
		}
		public long getInterval() {
			return saveInterval;
		}
		public void setInterval(long newInterval) {
			saveInterval = newInterval;
			setEnabled(getInterval() >= 0 && isEnabled());
		}
		@Override
		public void actionPerformed(ActionEvent e) {
			if(getDifference() >= getInterval()) {
				save();
			}
		}
	}
	
	/**
	 * Filter for pear review preferences
	 *
	 */
	private class PRPFilter extends javax.swing.filechooser.FileFilter 
			implements FileFilter, FilenameFilter, Serializable {
		private static final long serialVersionUID = -2411673420744789363L;
		public static final String EXTENSION = ".prp";
		public static final String DESCRIPTION = 
				"PearReview Preferences File (*" + EXTENSION + ")";
		@Override
		public boolean accept(File pathname) {
			if (pathname.isDirectory()) {
				return true;
			}
			
			String name = pathname.getName();
		
			return accept(pathname.getParentFile(), name);
		}
		@Override
		public String getDescription() {
			return DESCRIPTION;
		}
		@Override
		public String toString() {
			return EXTENSION;
		}
		@Override
		public boolean accept(File dir, String name) {
			return name.toLowerCase().endsWith(EXTENSION);
		}
	}
	
	/**
	 * Filter for pear review sessions
	 *
	 */
	private class PRSFilter extends javax.swing.filechooser.FileFilter 
			implements FileFilter, FilenameFilter, Serializable {
		private static final long serialVersionUID = -2411673420744789363L;
		public static final String EXTENSION = ".prs";
		public static final String DESCRIPTION = 
				"PearReview Session File (*" + EXTENSION + ")";
		@Override
		public boolean accept(File pathname) {
			if (pathname.isDirectory()) {
				return true;
			}
			
			String name = pathname.getName();
		
			return accept(pathname.getParentFile(), name);
		}
		@Override
		public String getDescription() {
			return DESCRIPTION;
		}
		@Override
		public String toString() {
			return EXTENSION;
		}
		@Override
		public boolean accept(File dir, String name) {
			return name.toLowerCase().endsWith(EXTENSION);
		}
	}
	
	/**
	 * Filter for pear review file history
	 *
	 */
	private class PRHFilter extends javax.swing.filechooser.FileFilter 
			implements FileFilter, FilenameFilter, Serializable {
		private static final long serialVersionUID = -2411673420744789363L;
		public static final String EXTENSION = ".prh";
		public static final String DESCRIPTION = 
				"PearReview File History File (*" + EXTENSION + ")";
		@Override
		public boolean accept(File pathname) {
			if (pathname.isDirectory()) {
				return true;
			}
			
			String name = pathname.getName();
		
			return accept(pathname.getParentFile(), name);
		}
		@Override
		public String getDescription() {
			return DESCRIPTION;
		}
		@Override
		public String toString() {
			return EXTENSION;
		}
		@Override
		public boolean accept(File dir, String name) {
			return name.toLowerCase().endsWith(EXTENSION);
		}
	}
	
	/**
	 * Gets called when user clicked on tab close button.
	 *
	 */
	private class ViewCloseButtonListener implements ViewCloseListener {
		private static final long serialVersionUID = 2364190536267958235L;
		@Override
		public void viewClosePerformed(ViewCloseEvent event) {
			closeView(event.getView());
		}
	}
	
	/**
	 * Gets called when user clicked on exit menu item
	 *
	 */
	private class ExitAction extends AbstractAction {
		private static final long serialVersionUID = -1222068929067459848L;
		public ExitAction() {
			putValue(Action.NAME, 
					Messages.getString("PearReview.menu.file.quit"));
			
			putValue(Action.SMALL_ICON, getResourceIcon("system-log-out.png"));
			
			KeyStroke ks = KeyStroke.getKeyStroke(KeyEvent.VK_Q, 
					Toolkit.getDefaultToolkit().getMenuShortcutKeyMask());
			putValue(Action.ACCELERATOR_KEY, ks);
		}
		@Override
		public void actionPerformed(ActionEvent e) {
			quit();
		}
	}
	
	/**
	 * Gets called when user clicked on new tab menu item
	 *
	 */
	private class NewTabAction extends AbstractAction {
		private static final long serialVersionUID = -1222068929067459848L;
		public NewTabAction() {
			putValue(Action.NAME, 
					Messages.getString("PearReview.menu.file.new_tab"));
			
			putValue(Action.SMALL_ICON, getResourceIcon("tab-new.png"));
			
			KeyStroke ks = KeyStroke.getKeyStroke(KeyEvent.VK_T, 
					Toolkit.getDefaultToolkit().getMenuShortcutKeyMask());
			putValue(Action.ACCELERATOR_KEY, ks);
		}
		@Override
		public void actionPerformed(ActionEvent e) {
			View v = createStartView();
			addView(v);
			setSelectedView(v);
		}
	}
	
	/**
	 * Gets called when user clicked on close tab menu item
	 *
	 */
	private class CloseTabAction extends AbstractAction {
		private static final long serialVersionUID = -1753886787301587301L;
		public CloseTabAction() {
			putValue(Action.NAME, 
					Messages.getString("PearReview.menu.file.close_tab"));
			
			KeyStroke ks = KeyStroke.getKeyStroke(KeyEvent.VK_W, 
					Toolkit.getDefaultToolkit().getMenuShortcutKeyMask());
			putValue(Action.ACCELERATOR_KEY, ks);
		}
		@Override
		public void actionPerformed(ActionEvent e) {
			View v = PearReview.this.getSelectedView();
			PearReview.this.closeView(v);
			
			if(PearReview.this.sizeView() <= 0) {
				PearReview.this.quit();
			}
		}
	}
	
	/**
	 * Gets called when user clicked on full screen menu item
	 *
	 */
	private class FullScreenAction extends AbstractAction {
		private static final long serialVersionUID = 3752599931605731118L;
		public FullScreenAction() {
			putValue(Action.NAME, 
					Messages.getString("PearReview.menu.view.fullscreen"));
			
			putValue(Action.SMALL_ICON, getResourceIcon("view-fullscreen.png"));
			
			KeyStroke ks = KeyStroke.getKeyStroke(KeyEvent.VK_F11, 0);
			putValue(Action.ACCELERATOR_KEY, ks);
		}
		@Override
		public void actionPerformed(ActionEvent e) {
			setFullScreen(!isFullScreen());
			putValue(Action.SELECTED_KEY, isFullScreen());
		}
	}
	
	/**
	 * Gets called when user clicked on about menu item
	 *
	 */
	private class AboutAction extends AbstractAction {
		private static final long serialVersionUID = -2818137615912384484L;
		public AboutAction() {
			putValue(Action.NAME, 
					Messages.getString("PearReview.menu.help.show_about"));
		}
		@Override
		public void actionPerformed(ActionEvent e) {
			about();
		}
	}
	
	/**
	 * Gets called when user clicked on license menu item
	 *
	 */
	private class LicenseAction extends AbstractAction {
		private static final long serialVersionUID = 747748612576560551L;
		public LicenseAction() {
			putValue(Action.NAME, 
					Messages.getString("PearReview.menu.help.show_license"));
		}
		@Override
		public void actionPerformed(ActionEvent e) {
			LicenseBox about = new LicenseBox(PearReview.this);
			glassPane.setFaded(true);
			about.setVisible(true);
			glassPane.setFaded(false);
		}
	}
	
	/**
	 * Gets called when user clicked on help menu item
	 *
	 */
	private class ShowHelpAction extends AbstractAction {
		private static final long serialVersionUID = -6584702985802652353L;
		public ShowHelpAction() {
			putValue(Action.NAME, 
					Messages.getString("PearReview.menu.help.show_help"));
			
			putValue(Action.SMALL_ICON, getResourceIcon("help-browser.png"));
			
			KeyStroke ks = KeyStroke.getKeyStroke(KeyEvent.VK_F1, 0);
			putValue(Action.ACCELERATOR_KEY, ks);
		}
		@Override
		public void actionPerformed(ActionEvent e) {
			HelpBox help = new HelpBox(PearReview.this);
			glassPane.setFaded(true);
			help.setVisible(true);
			glassPane.setFaded(false);
		}
	}
	
	/**
	 * Gets called when user clicked on update menu item or 
	 * VersionChecker notify finish of checking
	 *
	 */
	private class UpdateAction extends AbstractAction {
		private static final long serialVersionUID = -9172077684871478337L;
		private boolean userRequest = false;
		public UpdateAction() {
			putValue(Action.NAME, 
					Messages.getString("PearReview.menu.help.update"));
		}
		public void setBusy(boolean b) {
			setEnabled(!b);
		}
		@Override
		public void actionPerformed(ActionEvent e) {
			Object source = e.getSource();
			setBusy(!(source instanceof VersionChecker));
			
			if(source instanceof VersionChecker) {
				VersionChecker vc = (VersionChecker) source;
				Version version = vc.getVersion();
				Exception error = vc.getError();
				String history = vc.getHistory();
				
				if(error == null && version != null 
						&& version.compareTo(VERSION) > 0) {
					UpdateBox box = new UpdateBox(PearReview.this);
					box.setVersion(version);
					box.setHistory(history);
					glassPane.setFaded(true);
					box.setVisible(true);
					glassPane.setFaded(false);
				} else if(userRequest && error == null) {
					JOptionPane.showMessageDialog(PearReview.this, 
							Messages.getString("PearReview.update.is_updated"), 
							Messages.getString("PearReview.update.title"), 
							JOptionPane.INFORMATION_MESSAGE);
				} else if(userRequest && error != null) {
					JOptionPane.showMessageDialog(PearReview.this, 
							Messages.getString("PearReview.update.error"), 
							Messages.getString("PearReview.update.title"), 
							JOptionPane.INFORMATION_MESSAGE);
				}
			} else {
				userRequest = true;
				versionChecker.check();
			}
		}
	}
	
	/**
	 * Gets called when user clicked on preferences menu item
	 *
	 */
	private class PropertyAction extends AbstractAction {
		private static final long serialVersionUID = 1778650773293961389L;
		public PropertyAction() {
			putValue(Action.NAME, Messages.getString(
					"PearReview.menu.properties.application"));
			
			putValue(Action.SMALL_ICON, 
					getResourceIcon("preferences-system.png"));
		}
		@Override
		public void actionPerformed(ActionEvent e) {
			preferences();
		}
	}
	
	/**
	 * Gets called when user clicked on export session menu item
	 *
	 */
	private class ExportAction extends AbstractAction {
		private static final long serialVersionUID = -9017741145067583452L;
		public ExportAction() {
			putValue(Action.NAME, 
					Messages.getString("PearReview.menu.file.session.export"));
			putValue(Action.SMALL_ICON, getResourceIcon("export.png"));
		}
		@Override
		public void actionPerformed(ActionEvent e) {
			final JFileChooser saveDialog = new JFileChooser();
			saveDialog.setMultiSelectionEnabled(false);
			saveDialog.setAcceptAllFileFilterUsed(false);
			
			PRSFilter prsFilter = new PRSFilter();
			
			saveDialog.setFileFilter(prsFilter);
			
			glassPane.setFaded(true);
			int ret = saveDialog.showSaveDialog(PearReview.this);
			glassPane.setFaded(false);
				 
			if (JFileChooser.APPROVE_OPTION != ret)
				return;
			
			File selectedFile = saveDialog.getSelectedFile();
			if(!prsFilter.accept(selectedFile)) {
				String fileName = selectedFile.getName();
				fileName += PRSFilter.EXTENSION;
				selectedFile = new File(selectedFile.getParent(), fileName);
			}
			
			writePluginSaveData(selectedFile);
		}
	}
	
	/**
	 * Gets called when user clicked on import session menu item
	 *
	 */
	private class ImportAction extends AbstractAction {
		private static final long serialVersionUID = 5692295922336198278L;
		public ImportAction() {
			putValue(Action.NAME, 
					Messages.getString("PearReview.menu.file.session.import"));
			putValue(Action.SMALL_ICON, getResourceIcon("import.png"));
		}
		@Override
		public void actionPerformed(ActionEvent e) {
			final JFileChooser openDialog = new JFileChooser();
			openDialog.setMultiSelectionEnabled(false);
			
			PRSFilter prsFilter = new PRSFilter();
			
			openDialog.setFileFilter(prsFilter);
			
			glassPane.setFaded(true);
			int ret = openDialog.showOpenDialog(PearReview.this);
			glassPane.setFaded(false);
				 
			if (JFileChooser.APPROVE_OPTION != ret)
				return;
			
			File selectedFile = openDialog.getSelectedFile();
			
			readPluginSaveData(selectedFile);
		}
	}
}
